#include "linux/string.h"
#include "linux/common.h"

#define _U 0x01  /* upper */
#define _L 0x02  /* lower */
#define _D 0x04  /* digit */
#define _C 0x08  /* cntrl */
#define _P 0x10  /* punct */
#define _S 0x20  /* white space (space/lf/tab) */
#define _X 0x40  /* hex digit */
#define _SP 0x80 /* hard space (0x20) */

 unsigned char _ctype[] = {
    _C, _C, _C, _C, _C, _C, _C, _C,                                       /* 0-7 */
    _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C,              /* 8-15 */
    _C, _C, _C, _C, _C, _C, _C, _C,                                       /* 16-23 */
    _C, _C, _C, _C, _C, _C, _C, _C,                                       /* 24-31 */
    _S | _SP, _P, _P, _P, _P, _P, _P, _P,                                 /* 32-39 */
    _P, _P, _P, _P, _P, _P, _P, _P,                                       /* 40-47 */
    _D, _D, _D, _D, _D, _D, _D, _D,                                       /* 48-55 */
    _D, _D, _P, _P, _P, _P, _P, _P,                                       /* 56-63 */
    _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U,         /* 64-71 */
    _U, _U, _U, _U, _U, _U, _U, _U,                                       /* 72-79 */
    _U, _U, _U, _U, _U, _U, _U, _U,                                       /* 80-87 */
    _U, _U, _U, _P, _P, _P, _P, _P,                                       /* 88-95 */
    _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L,         /* 96-103 */
    _L, _L, _L, _L, _L, _L, _L, _L,                                       /* 104-111 */
    _L, _L, _L, _L, _L, _L, _L, _L,                                       /* 112-119 */
    _L, _L, _L, _P, _P, _P, _P, _C,                                       /* 120-127 */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                       /* 128-143 */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                       /* 144-159 */
    _S | _SP, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, /* 160-175 */
    _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P,       /* 176-191 */
    _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U,       /* 192-207 */
    _U, _U, _U, _U, _U, _U, _U, _P, _U, _U, _U, _U, _U, _U, _U, _L,       /* 208-223 */
    _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L,       /* 224-239 */
    _L, _L, _L, _L, _L, _L, _L, _P, _L, _L, _L, _L, _L, _L, _L, _L};      /* 240-255 */

#define __ismask(x) (_ctype[(int)(unsigned char)(x)])

#define islower(c) ((__ismask(c) & (_L)) != 0)
#define isupper(c) ((__ismask(c) & (_U)) != 0)

unsigned char __tolower(unsigned char c)
{
    if (isupper(c))
        c -= 'A' - 'a';
    return c;
}

unsigned char __toupper(unsigned char c)
{
    if (islower(c))
        c -= 'a' - 'A';
    return c;
}

int strncasecmp(const char *s1,char *s2, size_t len)
{
	unsigned char c1, c2;

	if (!len)
		return 0;

	do {
		c1 = *s1++;
		c2 = *s2++;
		if (!c1 || !c2)
			break;
		if (c1 == c2)
			continue;
		c1 = tolower(c1);
		c2 = tolower(c2);
		if (c1 != c2)
			break;
	} while (--len);
	return (int)c1 - (int)c2;
}

int strcasecmp( char *s1,  char *s2)
{
    int c1, c2;

    do
    {
        c1 = tolower(*s1++);
        c2 = tolower(*s2++);
    } while (c1 == c2 && c1 != 0);
    return c1 - c2;
}

void memset(void *src, int num, unsigned long len)
{
    unsigned char *tmp;
    int i = 0;

    if (!src || !len)
        return;
    tmp = src;
    for (i = 0; i < len; i++)
    {
        *tmp++ = num;
    }
}

void *memcpy(void *dest, void *src, unsigned long len)
{
    char *d = dest;
    char *s = src;

    if (!dest || !src || !len)
        return dest;

    while (len--)
        *d++ = *s++;

    return dest;
}

int strncmp(char *s1, char *s2, unsigned long n)
{
    if ((!s1 && !s2) || !n)
        return 0;
    
    if (!s1)
        return -1;
    
    if (!s2)
        return 1;

    while (*s1 && *s2 && (*s1 == *s2))
    {
        s1++;
        s2++;
        n--;
        if (n == 0)
            return 0;
    }

    return (*s1 - *s2);
}

int strcmp(char *s1, char *s2)
{
    if (!s1 && !s2)
        return 0;
    
    if (!s1)
        return -1;
    
    if (!s2)
        return 1;

    while (*s1 && *s2 && (*s1 == *s2))
    {
        s1++;
        s2++;
    }
    return (*s1 - *s2);
}

char *strcpy(char *dst, char *src)
{
    char *ret = dst;

    while ((*dst++ = *src++) != '\0')
        ;

    return ret;
}

char *strncpy(char *dest,  char *src, unsigned long len)
{
    int i = 0;
    char *temp = dest;

    while (i++ < len && (*temp++ = *src++) != '\0')
    {
    }

    if (*(temp) != '\0')
        *temp = '\0';

    return dest;
}

unsigned long strlen( char *str)
{
     char *eos = str;

    while (*eos++)
        ;

    return (eos - str - 1);
}

char *strchr( char *s, int c)
{
    while (*s)
    {
        if (*s == (char)c)
            return (char *)s;
        s++;
    }
    return (c == 0) ? (char *)s : NULL;
}

char *strrchr( char *s, int c)
{
    char *last = NULL;
    while (*s)
    {
        if (*s == (char)c)
            last = s;
        s++;
    }
    return (c == 0) ? (char *)s : (char *)last;
}

char *kbasename(char *path)
{
    char *tail = strrchr(path, '/');
    return tail ? tail + 1 : path;
}


unsigned long strnlen( char *s, unsigned long n)
{
    unsigned long len = 0;

    if (!s || !n)
        return 0;

    while (*s && n--)
    {
        len++;
        s++;
    }

    return len;
}

char * strchrnul(char *s, int c)
{
    while (*s && *s != (char)c)
        s++;

    return s;
}

char *strstr(char *haystack, char *needle)
{
    char *p1, *p2;

    if (!*needle)
        return haystack; // 如果 needle 为空字符串，返回 haystack

    for (; *haystack; haystack++)
    {
        p1 = haystack;
        p2 = needle;

        while (*p1 && *p2 && (*p1 == *p2))
        {
            p1++;
            p2++;
        }

        if (!*p2) // 如果 needle 已经完全匹配
            return haystack;
    }

    return NULL; // 没有找到匹配
}

long strcspn(char *s, char *reject)
{
    char *tmp;

    tmp = strstr(s, reject);
    if (tmp)
        return tmp - s;
    else
        return strlen(s);
}

char *strcat(char *dest, char *src)
{
    char *ptr = dest + strlen(dest);

    while (*src)
    {
        *ptr++ = *src++;
    }
    *ptr = '\0'; // 确保字符串以 null 结尾

    return dest;
}

int memcmp(void *s1, void *s2, unsigned long n)
{
    unsigned char *p1 = s1;
    unsigned char *p2 = s2;

    if (!s1 || !s2 || !n)
        return 0;

    while (n--)
    {
        if (*p1 != *p2)
            return (*p1 - *p2);
        p1++;
        p2++;
    }

    return 0;
}